package com.zha.boss.mvc.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zha.boss.dao.entity.UserPayConfig;
import com.zha.boss.dao.entity.UserPayInfo;
import com.zha.boss.dao.mapper.UserPayConfigMapper;
import com.zha.boss.dao.mapper.UserPayInfoMapper;
import com.zha.boss.enums.resp.RespCode;
import com.zha.boss.enums.status.PublicStatus;
import com.zha.boss.events.domain.NoticeMailEvent;
import com.zha.boss.exceptions.BossException;
import com.zha.boss.mvc.models.forms.config.UserPayConfigForm;
import com.zha.boss.mvc.models.forms.config.KqConfig;
import com.zha.boss.mvc.models.forms.config.WxConfig;
import com.zha.boss.mvc.service.MailService;
import com.zha.boss.mvc.service.UserPayConfigService;
import com.zha.boss.util.NoBuilderUtil;
import jakarta.annotation.Resource;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @Author: zha
 * @CreateTime: 2024年09月17日 10:56
 */
@Service
public class UserPayConfigServiceImpl implements UserPayConfigService {

    @Resource
    private UserPayConfigMapper userPayConfigMapper;
    @Resource
    private UserPayInfoMapper userPayInfoMapper;
    @Resource
    private MailService mailService;
    @Override
    public IPage<UserPayConfig> pageList(Integer pageNo, Integer pageSize) {
        QueryWrapper<UserPayConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("user_no", "pay_product_code");
        return userPayConfigMapper.selectPage(Page.of(pageNo, pageSize),queryWrapper);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addUserPayConfig(UserPayConfigForm userPayConfigForm) {
        // 查询 userNo, productCode 是否存在
        // 1. 判断 pay_config 表, user_no, product_code 是唯一的
        QueryWrapper<UserPayConfig> configQuery = new QueryWrapper<>();
        configQuery.eq("user_no", userPayConfigForm.getUserNo())
                .eq("pay_product_code", userPayConfigForm.getProductCode());
        UserPayConfig userPayConfig = userPayConfigMapper.selectOne(configQuery);
        if (userPayConfig != null) {
            throw new BossException(RespCode.CONFIG_USER_PRODUCT_EXISTS);
        }
        // 2. 添加支付配置到pay_config表
        userPayConfig = new UserPayConfig();
        userPayConfig.setId(NoBuilderUtil.getUUID());
        userPayConfig.setUserNo(userPayConfigForm.getUserNo());
        userPayConfig.setShopName(userPayConfigForm.getShopName());
        userPayConfig.setPayProductCode(userPayConfigForm.getProductCode());
        userPayConfig.setPayProductName(userPayConfigForm.getProductName());
        userPayConfig.setRiskDay(userPayConfigForm.getRiskDay());
        userPayConfig.setAppKey(NoBuilderUtil.getUUID());
        userPayConfig.setAppSecret(NoBuilderUtil.getUUID());
        userPayConfig.setMerchantServerIp(userPayConfigForm.getIpList());
        userPayConfig.setAutoSett("autoYes".equals(userPayConfigForm.getAutoSett())? "YES": "NO");
        userPayConfig.setRemark("创建商户支付产品配置");
        userPayConfig.setEditTime(new Date());
        userPayConfig.setStatus(PublicStatus.ENABLE.name());
        userPayConfigMapper.insert(userPayConfig);
        // 3. 记录第三方支付的参数 到user_pay_info表
        KqConfig kqConfig = userPayConfigForm.getKqConfig();
        if (kqConfig != null && StrUtil.isNotBlank(kqConfig.getMerchId())
                 && StrUtil.isNotBlank(kqConfig.getPublicFile())
                 && StrUtil.isNotBlank(kqConfig.getPrivateFile())
                 && StrUtil.isNotBlank(kqConfig.getQueryKey())){
            UserPayInfo userPayInfo = getUserPayInfo(userPayConfigForm, "K-Q", "快钱", JSONUtil.toJsonStr(kqConfig), "创建快钱支付方式");
            userPayInfoMapper.insert(userPayInfo);
        }
        // 3. 记录第三方支付的参数 到user_pay_info表
        WxConfig wxConfig = userPayConfigForm.getWxConfig();
        if (wxConfig != null && StrUtil.isNotBlank(wxConfig.getAppId())
                 && StrUtil.isNotBlank(wxConfig.getMerchId())){
            UserPayInfo userPayInfo = getUserPayInfo(userPayConfigForm, "W-X", "微信", JSONUtil.toJsonStr(wxConfig), "创建微信支付方式");
            userPayInfoMapper.insert(userPayInfo);
        }
        // 4. 发送通知邮件   商户号,  商户名称: appKey, appSecret,使用的支付产品code, 产品名称, 包含的支付方式
        mailService.sendSimpleMail(userPayConfig);
    }

    @Override
    public List<UserPayInfo> payInfoList(String userNo, String productCode) {
        QueryWrapper<UserPayInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_no", userNo)
               .eq("pay_product_code", productCode)
                .orderByAsc("pay_way_code");
        return userPayInfoMapper.selectList(queryWrapper);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeUserPayConfig(String userNo, String productCode) {
        QueryWrapper<UserPayInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_no", userNo)
                .eq("pay_product_code", productCode)
                .orderByAsc("pay_way_code");
        userPayInfoMapper.delete(queryWrapper);
        QueryWrapper<UserPayConfig> configQuery = new QueryWrapper<>();
        configQuery.eq("user_no", userNo)
                .eq("pay_product_code", productCode);
        userPayConfigMapper.delete(configQuery);
    }

    private static UserPayInfo getUserPayInfo(UserPayConfigForm userPayConfigForm, String payWayCode, String payWayName, String config, String payWayRemark) {
        UserPayInfo userPayInfo = new UserPayInfo();
        userPayInfo.setId(NoBuilderUtil.getUUID());
        userPayInfo.setPayProductCode(userPayConfigForm.getProductCode());
        userPayInfo.setUserNo(userPayConfigForm.getUserNo());
        userPayInfo.setShopName(userPayConfigForm.getShopName());
        userPayInfo.setPayWayCode(payWayCode);
        userPayInfo.setPayWayName(payWayName);
        userPayInfo.setPayConfig(config);
        userPayInfo.setRemark(payWayRemark);
        userPayInfo.setEditTime(new Date());
        userPayInfo.setStatus(PublicStatus.ENABLE.name());
        return userPayInfo;
    }
}
